package com.situ.crm2026.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.situ.crm2026.dao.CourseMapper;
import com.situ.crm2026.model.Course;

import com.situ.crm2026.service.CourseService;
import org.apache.ibatis.annotations.CacheNamespace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Service
@CacheConfig(cacheNames = "com.situ.crm2026.impl.courseServiceImpl")
public class CourseServiceImpl implements CourseService {

    @Autowired
    private CourseMapper courseMapper;
//    + '-' + (#csb?.name ?: 'all')
//    这是最复杂也最巧妙的部分：
//
//            🔸 #csb
//    表示方法参数中名为 csb 的对象（可能是 CourseSearchBO，即业务查询条件对象）；
//            🔸 ?.（安全导航操作符）
//    如果 csb 为 null，不会抛出空指针异常，而是返回 null；
//    避免 NPE（NullPointerException）。
//            🔸 ?: 'all'（Elvis 操作符）
//    如果前面的值为 null 或 false，则使用后面的默认值；
//    所以：
//    如果 csb 不为 null 且 name 有值 → 使用 csb.name
//    如果 csb 为 null 或 name 为 null → 使用 'all'
  //  @Cacheable(key = "'course-page-' + #page.current + '-' + #page.size + '-' + (#csb?.name ?: 'all') ")
    @Override
    public Page<Course> findAll(Page<Course> page, Course csb) {
        try {
            return courseMapper.findCoursesWithBookedCount(page, csb);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("查询课程失败: " + e.getMessage(), e);
        }
    }
@CacheEvict(allEntries = true)
    @Override
@Transactional
    public int deleteByIds(List<Integer> ids) {
        try {
            return courseMapper.deleteBatchIds(ids);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("删除课程失败: " + e.getMessage(), e);
        }
    }
    @CacheEvict(allEntries = true)
    @Override
    public boolean save(Course course) {
        try {
            // 检查时间和教室是否冲突
            if (hasTimeAndRoomConflict(course)) {
                return false;
            }
            return courseMapper.insert(course) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("保存课程失败: " + e.getMessage(), e);
        }
    }
    @CacheEvict(allEntries = true)
    @Override
    public boolean update(Course course) {
        try {    // 检查时间和教室是否冲突
            if (hasTimeAndRoomConflict(course)) {
return false;            }
            return courseMapper.updateById(course) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("更新课程失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Course getCourseDetailById(Integer id) {
        try {
            return courseMapper.selectCourseWithMembersById(id);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("查询课程详情失败: " + e.getMessage(), e);
        }
    }
    @Override
    public List<Map<String, Object>> getMembersByCourseId(Integer courseId) {
        try {
            return courseMapper.findMembersByCourseId(courseId);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("查询课程会员列表失败: " + e.getMessage(), e);
        }
    }

    //实现时间和教室冲突的检查办法
    @Override
    public boolean hasTimeAndRoomConflict(Course newCourse) {
        //获取新课程的时间和教室信息
        LocalDateTime newStart = newCourse.getStartTime();

        int duration = Integer.parseInt(newCourse.getDuration());
        LocalDateTime newEnd = newStart.plusMinutes(duration);
        String  newRoom = newCourse.getRoom();

        if(newRoom==null||newRoom.isEmpty()){
            return false;
        }
        //构造查询条件 检查同一教室的课程
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Course::getRoom, newRoom);

        //如果是更新操作,则排除自己
        if(newCourse.getId()!=null){
            queryWrapper.ne(Course::getId, newCourse.getId());
        }
        /*重点来了**///1.查询同一教室的课程
        List<Course> conflictingCourses = courseMapper.selectList(queryWrapper);
    //2.查询同一教室的课程时间
        for (Course conflictingCourse : conflictingCourses) {
            LocalDateTime conflictingStart = conflictingCourse.getStartTime();
            int conflictingDuration = Integer.parseInt(conflictingCourse.getDuration());
            LocalDateTime conflictingEnd = conflictingStart.plusMinutes(conflictingDuration);
            //3.判断时间冲突
            // 冲突公式:  A_start < B_end && A_end > B_start
            boolean isOverlapping = newStart.isBefore(conflictingEnd) && newEnd.isAfter(conflictingStart);
            if (isOverlapping){
                return true;
            }
        }
        return false;
    }


}
